/*
 * Copyright (c) 2023 Beijing HuaQing YuanJian Education Technology Co., Ltd
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include "hi_i2c.h"
#include "hi_io.h"
#include "hi_gpio.h"

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "mynfc.h"

#if 0
osThreadId_t Task1_ID; // 任务1设置为低优先级任务
#define TASK_STACK_SIZE (1024 * 10)
#endif

#define NT3H1X_SLAVE_ADDRESS 0x55 // NT3H NFC芯片的7位地址
#define MANUFACTORING_DATA_REG 0x0
#define USER_START_REG 0x1   // 用户可操作空间-开始地址

// NT3H1101                     // for th 1K
#define USER_END_REG   0x38 // just the first 8 bytes for th 1K
#define CONFIG_REG	   0x3A

#define SRAM_START_REG 0xF8 // SRAM空间的-开始地址
#define SRAM_END_REG 0xFB   // SRAM空间的-结束地址
#define SESSION_REG 0xFE
#define SERIAL_NUM_LEN 6

#define DELAY_WRITE 300000

static uint8_t nfcPageBuffer[NFC_PAGE_SIZE];
uint8_t *nfcBuf = NULL;

/**
 * @brief  NFC引脚初始化
 * @note
 * @retval
 */
int i2cInit(void)
{
    int ret;

    // gpio_9 复用为 I2C_SCL
    hi_io_set_pull(HI_IO_NAME_GPIO_9, HI_IO_PULL_UP);
    hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_I2C0_SCL);
    // gpio_10 复用为 I2C_SDA
    hi_io_set_pull(HI_IO_NAME_GPIO_10, HI_IO_PULL_UP);
    hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_I2C0_SDA);

    ret = hi_i2c_init(HI_I2C_IDX_0, I2C_RATE_DEFAULT);
    if (ret != HI_ERR_SUCCESS) {
        printf("I2C init status is 0x%x!!!\r\n", ret);
        return ret;
    }
    printf("I2C init is succeeded!!!\r\n");

    return ret;
}

static int readReg(uint8_t address, uint8_t *block_data)
{
    hi_u32 ret = 0;
    hi_i2c_data nt3h1101_i2c_data = {0};
    uint8_t buffer[1] = {address};
    //int i = 0;
    nt3h1101_i2c_data.send_buf = buffer;
    nt3h1101_i2c_data.send_len = 1;
    nt3h1101_i2c_data.receive_buf = block_data;
    nt3h1101_i2c_data.receive_len = NFC_PAGE_SIZE;

    ret = hi_i2c_writeread(HI_I2C_IDX_0, (NT3H1X_SLAVE_ADDRESS << 1) | 0x00, &nt3h1101_i2c_data);
    if (HI_ERR_SUCCESS != ret) {
        printf("===== Error: I2C read addr 0x%x, ret = 0x%x! =====\r\n", address, ret);
        return ret;
    }
    /*
    printf("=====Read Success:IC read addr 0x%x, ret = 0x%x! =====\r\n", address, ret);

    for (i = 0; i < NFC_PAGE_SIZE; i++)
    {
        printf("0x%x ", block_data[i]);
    }
    printf("\n");
    */
    /*
    if (address == 6 || address == 7 || address == 8)
    {
        printf("Read last data is %s \n", block_data);
    }
    */
    return ret;
}

static int writeReg(uint8_t address, uint8_t *block_data, int block_len)
{
	hi_u32 ret = 0;
    hi_i2c_data nt3h1101_i2c_data1 = {0};
	uint8_t *data = malloc(NFC_PAGE_SIZE + 2);
	
	memset(data, 0, NFC_PAGE_SIZE + 2);
	data[0] = address;
	memcpy(data + 1, block_data, block_len);

    nt3h1101_i2c_data1.send_buf = data;
    nt3h1101_i2c_data1.send_len = NFC_PAGE_SIZE + 1;

    ret = hi_i2c_write(HI_I2C_IDX_0, (NT3H1X_SLAVE_ADDRESS << 1) | 0x00, &nt3h1101_i2c_data1);
    if (ret != 0) {
        printf("===== Error: I2C write status1 = 0x%x, str is %s! =====\r\n", ret, data);
        return ret;
    }
    /*
    if ( address == 6 || address == 7 || address == 8 )
    {
        printf("Write data + 1 is %s\n", data + 1);
    }
    */

    usleep(DELAY_WRITE);
	return ret;
}

static int readHeaderLen(int *len)
{
    int ret = 0;
    //int i = 0;
    ret = readReg(USER_START_REG, nfcPageBuffer);
    if(HI_ERR_SUCCESS != ret)
    {
        return ret;
    }

    /*第2位是长度位，最大255*/
    *len = nfcPageBuffer[NDEF_PROTOCOL_LENGTH_OFFSET];
    printf("nfc len is %d\n", *len);

    if ((NDEF_PROTOCOL_HEAD_SIZE + NDEF_PROTOCOL_PAYLOAD_HEAD_SIZE) > len)
    {
        printf("len is too short.\n");
        return -1;
    }
    /*
    for (i = 0; i < NFC_PAGE_SIZE; i ++)
    {
        printf("0x%x ", nfcPageBuffer[i]);
    }
    printf("\n");
    */
    return HI_ERR_SUCCESS;
}

int readNfc(void)
{
    int len = 0;
    int reg = 0;
    int i = 0;
    int tmp = 0;
    int ret = -1;

    ret = readHeaderLen(&len);
    if (0 != ret)
    {
        printf("Read failed. ret is %d\n", ret);
        return ret;
    }

    nfcBuf = malloc(len + NDEF_HEADER_SIZE);
    if (NULL == nfcBuf)
    {
        printf("Molloc mem failed.\n");
        return HI_ERR_MALLOC_FAILUE;
    }
    memset(nfcBuf , 0 , len + NDEF_HEADER_SIZE);

    tmp = (len + NDEF_HEADER_SIZE) % NFC_PAGE_SIZE;
    if (0 == tmp)
    {
        reg = (len + NDEF_HEADER_SIZE) / NFC_PAGE_SIZE;
    }
    else
    {
        reg = (len + NDEF_HEADER_SIZE) / NFC_PAGE_SIZE + 1;
    }

    for (i = 0; i < reg; i++)
    {
        //读取每一页的数据
        ret = readReg(USER_START_REG + i, nfcPageBuffer);
        if(HI_ERR_SUCCESS != ret)
        {
            return ret;
        }
        
        if (i != reg - 1)//如果不是最后一页，拷贝一页数据
        {
            memcpy(nfcBuf + i * NFC_PAGE_SIZE, nfcPageBuffer, NFC_PAGE_SIZE);
        }
        else if (0 == tmp)//如果是最后一页，且能除尽，也拷贝一页
        {
            memcpy(nfcBuf + i * NFC_PAGE_SIZE, nfcPageBuffer, NFC_PAGE_SIZE);
        }
        else//如果是最后一页，且不能能除尽，拷贝余数
        {
            memcpy(nfcBuf + i * NFC_PAGE_SIZE, nfcPageBuffer, tmp);
        }

    }

    printf("start print ndefBuff.\r\n");
    for (i = 0; i < len + NDEF_HEADER_SIZE; i++) {
        printf("0x%x ", nfcBuf[i]);
    }

    printf("\nEnd nfc.\r\n");

    return HI_ERR_SUCCESS;
}


int writeNfc(uint8_t *data)
{
	int len = strlen((char *)data);
	int tmp = len % NFC_PAGE_SIZE;
	int writeNumber = 0;
	int i = 0;
	int ret = -1;

    printf("Data is \n");
    for (i = 0; i < len; i++)
    {
        printf("0x%x ", data[i]);
    }
    

	if (0 == tmp)
	{
		writeNumber = len / NFC_PAGE_SIZE;
	}
	else
	{
		writeNumber = len / NFC_PAGE_SIZE + 1;
	}
    
    printf("\nEnd Data, tmp is %d, len is %d, writeNumber is %d\n", tmp, len, writeNumber);
	
    for (i = 0; i < writeNumber; i++)
	{
		if (i < writeNumber - 1)//如果不是最后一页，写一页数据
		{
			ret = writeReg(USER_START_REG + i, data + i * NFC_PAGE_SIZE,  NFC_PAGE_SIZE);
		}
		else if (0 == tmp)//如果是最后一页，能除尽，写一页数据
		{
			ret = writeReg(USER_START_REG + i, data + i * NFC_PAGE_SIZE,  NFC_PAGE_SIZE);
		}
		else//如果是最后一页，但不能除尽，则写余数数据
		{
            //printf("data is %s, i is %d\n", data + i * NFC_PAGE_SIZE, i);
			ret = writeReg(USER_START_REG + i, data + i * NFC_PAGE_SIZE,  tmp);
		}
		if (HI_ERR_SUCCESS != ret)
		{
			printf("Write info failed, info is %s.\n", data);
			return ret;
		}
	}
	
    printf("Write success.\n");
    return 0;
}

#if 0
void Task1(void)
{
    int ret;

    ret = i2cInit();
    if (HI_ERR_SUCCESS != ret)
    {
        printf("Init i2c failed.\n");
        return;
    }

    ret = readNfc();
    printf("\nRead Nfc %d.\n", ret);
    while (1) {
        sleep(1); // 1 s
    }
}


static void testNfc(void)
{
    printf("Enter testNfc()!\r\n");

    osThreadAttr_t options;
    options.name = "thread_1";
    options.attr_bits = 0;
    options.cb_mem = NULL;
    options.cb_size = 0;
    options.stack_mem = NULL;
    options.stack_size = TASK_STACK_SIZE;
    options.priority = osPriorityNormal;

    Task1_ID = osThreadNew((osThreadFunc_t)Task1, NULL, &options);
    if (Task1_ID != NULL) {
        printf("ID = %d, Create Task1_ID is OK!\r\n", Task1_ID);
    }
}
SYS_RUN(testNfc);

#endif